home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / ViewerTest / ViewerTest.c < prev    next >
Encoding:
Text File  |  1995-11-09  |  13.3 KB  |  714 lines  |  [TEXT/CWIE]

  1. //
  2. //    ViewerTest.c
  3. //
  4. //    Theron's first QuickDraw 3D program
  5. //
  6. //    A simple QD3D Viewer application.  Allows the user to open a 3DMF file
  7. //    and display the object in it using the standard QD3D viewer.
  8. //
  9. //    Much of this was taken from two books:
  10. //        3D Graphics Programming With QuickDraw 3D (Apple's QD3D book)
  11. //        Tricks of The Mac Game Programming Gurus
  12. //    With much coming from Inside Macintosh and The Mac C Programming Primer
  13. //
  14. //    Version 0.1
  15. //
  16. //    The following libraries are included in the CW7 project:
  17. //        InterfaceLib
  18. //        QuickDraw3DAcceleratorLib
  19. //        QuickDraw3DLib
  20. //        QuickDraw3DViewerLib (must be imported "weak")
  21. //        MathLib
  22. //        MWCRuntime.Lib
  23. //
  24. //    For all I know, not all of these are neccessary...
  25.  
  26.  
  27. #include <Gestalt.h>
  28. #include <CodeFragments.h>
  29. #include <Dialogs.h>
  30.  
  31. //    and all of the QD3D header files, just in case...
  32. #include <QD3d.h>
  33. #include <QD3DAcceleration.h>
  34. #include <QD3DCamera.h>
  35. #include <QD3DController.h>
  36. #include <QD3DDrawContext.h>
  37. #include <QD3DErrors.h>
  38. #include <QD3DGeometry.h>
  39. #include <QD3DGroup.h>
  40. #include <QD3DIO.h>
  41. #include <QD3DLight.h>
  42. #include <QD3DMath.h>
  43. #include <QD3DPick.h>
  44. #include <QD3DRenderer.h>
  45. #include <QD3DSet.h>
  46. #include <QD3DShader.h>
  47. #include <QD3DStorage.h>
  48. #include <QD3DString.h>
  49. #include <QD3DStyle.h>
  50. #include <QD3DTransform.h>
  51. #include <QD3DView.h>
  52. #include <QD3DViewer.h>
  53.  
  54.  
  55. //
  56. //    Constants
  57. //
  58. #define    kNilFilterProc    nil
  59. #define kEmptyString    "\p"
  60. #define    kSleep            32767
  61. #define    kMoveToFront    (WindowPtr)-1L
  62.  
  63. #define    kBaseResID        700
  64. #define    kErrorResID        kBaseResID
  65. #define    kAboutResID        kBaseResID
  66.  
  67. #define mApple            kBaseResID + 0
  68. #define    iAbout            1
  69.  
  70. #define    mFile            kBaseResID + 1
  71. #define    iOpen            1
  72. #define    iClose            2
  73. //    item 3 is a separator
  74. #define    iQuit            4
  75.  
  76. #define    mEdit            kBaseResID + 2
  77. #define    iUndo            1
  78. //    item 2 is a separator
  79. #define    iCut            3
  80. #define    iCopy            4
  81. #define    iPaste            5
  82. #define    iClear            6
  83.  
  84.  
  85. //
  86. //    Global Variables
  87. //
  88. Boolean                gDone, gWindowOpen, gFileOpen, gViewerActive;
  89. WindowPtr            gWindow;
  90. short                gOpenFileRefNum;
  91. TQ3ViewerObject        gViewer;
  92.  
  93.  
  94. //
  95. //    Prototypes
  96. //
  97. void            ToolBoxInit( void );
  98. void            MenuBarInit( void );
  99. void            MainLoop( void );
  100. void            DoEvent( EventRecord *eventPtr );
  101. void            DoUpdate( EventRecord *eventPtr );
  102. void            HandleMouseDown( EventRecord *eventPtr );
  103. void            HandleMenuChoice( long    menuChoice );
  104. void            SetFileMenuStuff( void );
  105. void            SetEditMenuStuff( void );
  106. void            HandleAppleChoice( short item );
  107. void            ShowAboutBox( void );
  108. void            HandleFileChoice( short item );
  109. void            Open3DMFFile( void );
  110. void            Close3DMFFile( void );
  111. Boolean            MyEnvironmentHas3DViewer( void );
  112. Boolean            CheckGestaltFor3D( void );
  113. void            DisplayFatalError( Str255 errorString );
  114. void            DisplayAlert( Str255 errorString );
  115. void            OpenMyWindow( Str255 windowTitle );
  116. void            CloseMyWindow( void );
  117. void            CreateViewerInWindow( void );
  118. TQ3ViewerObject    MyCreateViewer( WindowPtr myWindow );
  119.  
  120.  
  121. //
  122. //    The Routines
  123. //
  124.  
  125.  
  126. //
  127. //    ToolBoxInit
  128. //
  129. void    ToolBoxInit( void )
  130. {
  131.     InitGraf( &qd.thePort );
  132. /*    InitGraf( &thePort );    */    //    This is how it's done in Think C...
  133.     InitFonts();
  134.     InitWindows();
  135.     InitMenus();
  136.     TEInit();
  137.     InitDialogs( nil );
  138.     InitCursor();
  139. }
  140.  
  141.  
  142. //
  143. //    MenuBarInit
  144. //
  145. void    MenuBarInit( void )
  146. {
  147.     Handle        menuBar;
  148.     MenuHandle    menu;
  149.     OSErr        myErr;
  150.     
  151.     menuBar = GetNewMBar( kBaseResID );    //    load the menubar resource
  152.     if ( menuBar == nil )
  153.         DisplayFatalError( "\pERROR: could not load menu resource!" );
  154.     
  155.     SetMenuBar( menuBar );                //    make it the current menubar
  156.     
  157.     menu = GetMHandle( mApple );        //    get a handle to the apple menu
  158.     AddResMenu( menu, 'DRVR' );            //    add the desk accessories to the Apple menu
  159.     
  160.     DrawMenuBar();                        //    draw the menu bar
  161. }
  162.  
  163.  
  164. //    MainLoop
  165. //
  166. void    MainLoop( void )
  167. {
  168.     EventRecord    event;
  169.     Boolean        isViewerEvent;
  170.     
  171.     gDone = false;
  172.     while ( gDone == false )
  173.     {
  174.         if ( WaitNextEvent( everyEvent, &event, kSleep, nil ) )
  175.         {
  176.             //    Let the 3D viewer handle the event if it should:
  177.             if ( Q3ViewerEvent( gViewer, &event ) == false )
  178.                 DoEvent( &event );    //    Otherwise, it's my responsibility
  179.         }
  180.     }
  181. }
  182.  
  183.  
  184. //
  185. //    DoEvent
  186. //
  187. void    DoEvent( EventRecord *eventPtr )
  188. {
  189.     char    theChar;
  190.     
  191.     switch ( eventPtr->what )
  192.     {
  193.         case kHighLevelEvent:
  194.             break;
  195.         case mouseDown:
  196.             HandleMouseDown( eventPtr );
  197.             break;
  198.         case mouseUp:
  199.             // No real need for mouseUp events...
  200.             break;
  201.         case keyDown:
  202.         case autoKey:
  203.             theChar = eventPtr->message & charCodeMask;
  204.             if ( (eventPtr->modifiers & cmdKey) != 0)
  205.                 HandleMenuChoice( MenuKey( theChar ) );
  206.             break;
  207.         case keyUp:
  208.             //    No real need for keyUp events...
  209.             break;
  210.         case updateEvt:
  211.             DoUpdate( eventPtr );
  212.             break;
  213.         case diskEvt:
  214.             break;
  215.         case activateEvt:
  216.             break;
  217.         case networkEvt:
  218.             break;
  219.         case driverEvt:
  220.             break;
  221.         case app1Evt:
  222.             break;
  223.         case app2Evt:
  224.             break;
  225.         case app3Evt:
  226.             break;
  227.         case osEvt:
  228.             break;
  229.     }
  230. }
  231.  
  232.  
  233. //
  234. //    DoUpdate
  235. //
  236. void    DoUpdate( EventRecord *eventPtr )
  237. {
  238.     WindowPtr        window;
  239.     
  240.     window = (WindowPtr) eventPtr->message;
  241.     
  242.     BeginUpdate( window );
  243.     
  244.     //    Do any update-specific tasks here
  245.     //    Right now, it's just a dummy thing so the program doesn't
  246.     //        screech to a grinding halt when something covers the
  247.     //        window...
  248.     
  249.     EndUpdate( window );
  250. }
  251.  
  252.  
  253. //
  254. //    HandleMouseDown
  255. //
  256. void    HandleMouseDown( EventRecord *eventPtr )
  257. {
  258.     WindowPtr    window;
  259.     short        thePart;
  260.     long        menuChoice;
  261.     Boolean        windowGoAway;
  262.     
  263.     thePart = FindWindow( eventPtr->where, &window );
  264.     
  265.     switch ( thePart )
  266.     {
  267.         case inMenuBar:
  268.             menuChoice = MenuSelect( eventPtr->where );    //    do the menu thing
  269.             HandleMenuChoice( menuChoice );
  270.             break;
  271.         case inSysWindow:
  272.             SystemClick( eventPtr, window );
  273.             break;
  274.         case inContent:
  275.             //    I may not need this, because I will only have one window...
  276.             break;
  277.         case inDrag:
  278.             DragWindow( window, eventPtr->where, &qd.screenBits.bounds );
  279. //    In Think C or Symantec C++, the following would work:
  280. //            DragWindow( window, eventPtr->where, &screenBits.bounds );
  281.             Q3ViewerSetBounds( gViewer, &(window->portRect) );
  282.             Q3ViewerDraw( gViewer );
  283.             break;
  284.         case inGoAway:
  285.             windowGoAway = TrackGoAway( window, eventPtr->where );
  286.             if ( windowGoAway )
  287.             {
  288.                 Close3DMFFile();
  289.             }
  290.             break;
  291.     }
  292. }
  293.  
  294.  
  295. //
  296. //    HandleMenuChoice
  297. //
  298. void    HandleMenuChoice( long    menuChoice )
  299. {
  300.     short    menu;
  301.     short    item;
  302.     
  303.     if ( menuChoice != 0 )
  304.     {
  305.         menu = HiWord( menuChoice );
  306.         item = LoWord( menuChoice );
  307.         
  308.         switch ( menu )
  309.         {
  310.             case mApple:
  311.                 HandleAppleChoice( item );
  312.                 break;
  313.             case mFile:
  314.                 HandleFileChoice( item );
  315.                 break;
  316.             case mEdit:
  317.                 
  318.                 break;
  319.         }
  320.         HiliteMenu( 0 );
  321.     }
  322. }
  323.  
  324.  
  325. //
  326. //    SetFileMenuStuff
  327. //
  328. void SetFileMenuStuff( void )
  329. {
  330.     MenuHandle    myMenu;
  331.     
  332.     myMenu = GetMenuHandle( mFile );
  333.  
  334.     if ( gWindowOpen )
  335.         EnableItem( myMenu, iClose );
  336.     else
  337.         DisableItem( myMenu, iClose );
  338. }
  339.  
  340.  
  341. //
  342. //    SetEditMenuStuff
  343. //
  344. void SetEditMenuStuff( void )
  345. {
  346.     MenuHandle    myMenu;
  347.     
  348.     myMenu = GetMenuHandle( mEdit );
  349.     
  350.     DisableItem( myMenu, iUndo );
  351.     DisableItem( myMenu, iCut );
  352.     DisableItem( myMenu, iCopy );
  353.     DisableItem( myMenu, iPaste );
  354.     DisableItem( myMenu, iClear );
  355. }
  356.  
  357.  
  358. //
  359. //    HandleAppleChoice
  360. //
  361. void    HandleAppleChoice( short item )
  362. {
  363.     MenuHandle    appleMenu;
  364.     Str255        accName;
  365.     short        accNumber;
  366.     
  367.     switch ( item )
  368.     {
  369.         case iAbout:
  370.             ShowAboutBox();
  371.             break;
  372.         default:
  373.             appleMenu = GetMHandle( mApple );
  374.             GetItem( appleMenu, item, accName );
  375.             accNumber = OpenDeskAcc( accName );
  376.             break;
  377.     }
  378. }
  379.  
  380.  
  381. //
  382. //    ShowAboutBox
  383. //
  384. void    ShowAboutBox( void )
  385. {
  386.     DialogPtr    myDialog;
  387.     
  388.     myDialog = GetNewDialog( kAboutResID, nil, kMoveToFront );
  389.     ShowWindow( myDialog );
  390.     DrawDialog( myDialog );
  391.     
  392.     /*    Wait until the user releases the mouse button.
  393.      *    If the user holds down the mouse when a click causes a message to be displayed,
  394.      *    we must wait until they release the button before checking for a click (see below)
  395.      *    to clear the dialog - so they at least have a chance to see it.
  396.      *    NOTE THE SEMICOLON!
  397.      *    This is a loop which waits until the mouse button is not down.
  398.      */
  399.     while ( Button() );
  400.     
  401.     /*    Now, wait until the user clicks:
  402.      *    NOTE THE SEMICOLON!
  403.      *    This is a loop which waits until the mouse is clicked.
  404.      */
  405.     while ( ! Button() );
  406.     
  407.     /*    clear the event queue so the click doesn't do anything:    */
  408.     FlushEvents( everyEvent, 0 );
  409.     
  410.     DisposeDialog( myDialog );    /*    Get rid of the dialog    */
  411. }
  412.  
  413.  
  414. //
  415. //    HandleFileChoice
  416. //
  417. void    HandleFileChoice( short item )
  418. {
  419.     switch ( item )
  420.     {
  421.         case iOpen:
  422.             Open3DMFFile();
  423.             //    This will have to do much more...
  424.             //    Put up open file dialog box
  425.             //    Open the file
  426.             //    Pass it to the viewer
  427.             //
  428.             //    This is only temporary, to make it do something:
  429. //            OpenMyWindow();
  430.             break;
  431.         case iClose:
  432.             Close3DMFFile();
  433.             break;
  434.         case iQuit:
  435.             Close3DMFFile();    //    Close the window if it's open
  436.             gDone = true;
  437.             break;
  438.     }
  439. }
  440.  
  441.  
  442. //
  443. //    Open3DMFFile
  444. //
  445. void Open3DMFFile( void )
  446. {
  447.     StandardFileReply    myReply;
  448.     FSSpec                mySpec;
  449.     SFTypeList            myTypes;
  450.     OSErr                myErr;
  451.     short                myFileRefNum;
  452.     
  453.     //    Open only 3DMF files
  454.     myTypes[0] = '3DMF';
  455.     
  456.     //    Put up the standard get file dialog box
  457.     StandardGetFile( nil, 1, myTypes, &myReply );
  458.     
  459.     if ( myReply.sfGood )    //    User hit Open...
  460.     {
  461.         //    If there's already a file open, close it:
  462.         Close3DMFFile();
  463.  
  464.         //    Open the new file:
  465.         mySpec = myReply.sfFile;
  466.         myErr = FSpOpenDF( &mySpec, fsRdWrPerm, &myFileRefNum );
  467.         if ( myErr != noErr )
  468.         {
  469.             DisplayAlert( "\pERROR: could not open file" );
  470.         }
  471.         else
  472.         {
  473.             gFileOpen = true;
  474.             gOpenFileRefNum = myFileRefNum;
  475.             OpenMyWindow( mySpec.name );
  476.             //    Now, create a viewer in the window
  477.             CreateViewerInWindow();
  478.             Q3ViewerUseFile( gViewer, gOpenFileRefNum );
  479.         }
  480.     }
  481. }
  482.  
  483. void Close3DMFFile( void )
  484. {
  485.     OSErr    myErr;
  486.         
  487.     if ( gFileOpen )
  488.     {
  489.         //    Dispose of the viewer:
  490.         if ( gViewerActive )
  491.         {
  492.             myErr = Q3ViewerDispose( gViewer );
  493.             if ( myErr != noErr )
  494.                 DisplayAlert( "\pERROR: could not dispose of viewer" );
  495.             else
  496.                 gViewerActive = false;
  497.         }
  498.         
  499.         //    Close the window
  500.         if ( gWindowOpen )
  501.         {
  502.             CloseMyWindow();    //    Close the current window
  503.         }
  504.         
  505.         //    Close the file
  506.         if ( gFileOpen )
  507.         {
  508.             myErr = FSClose( gOpenFileRefNum );
  509.             if ( myErr != noErr )
  510.                 DisplayAlert( "\pERROR: could not close file" );
  511.             else
  512.                 gFileOpen = false;
  513.         }
  514.     }
  515. }
  516.  
  517.  
  518. //
  519. //    MyEnvironmentHas3DViewer
  520. //        For this routine to work, we have to establish a
  521. //        "weak" link to the QuickDraw3DViewerLib library.
  522. //
  523. Boolean    MyEnvironmentHas3DViewer( void )
  524. {
  525.     return((Boolean)Q3ViewerNew != kUnresolvedSymbolAddress);
  526. }
  527.  
  528.  
  529. //
  530. //    CheckGestaltFor3D
  531. //
  532. Boolean    CheckGestaltFor3D( void )
  533. {
  534.     OSErr    err;
  535.     long    feature;
  536.     
  537.     err = Gestalt( gestaltQD3DViewer, &feature );
  538.     
  539.     if ( err != noErr )
  540.     {
  541.         return false;
  542.     }
  543.     else
  544.     {
  545.         if ( feature == gestaltQD3DViewerAvailable )
  546.             return true;
  547.         else
  548.             return false;
  549.     }
  550. }
  551.  
  552.  
  553. //
  554. //    DisplayFatalError
  555. //        Display a stop alert box with a single text string, then quit
  556. void DisplayFatalError( Str255 errorString )
  557. {
  558.     ParamText( errorString, kEmptyString, kEmptyString, kEmptyString );
  559.     StopAlert( kErrorResID, kNilFilterProc );
  560.     ExitToShell();
  561. }
  562.  
  563.  
  564. //
  565. //    DisplayAlert
  566. //
  567. void DisplayAlert( Str255 errorString )
  568. {
  569.     ParamText( errorString, kEmptyString, kEmptyString, kEmptyString );
  570.     StopAlert( kErrorResID, kNilFilterProc );
  571. }
  572.  
  573.  
  574. //
  575. //    OpenMyWindow
  576. //
  577. void OpenMyWindow( Str255 windowTitle )
  578. {
  579.     WindowPtr    tempWindow;
  580.     
  581.     if ( gWindowOpen )
  582.     {
  583.         CloseMyWindow();    //    Close the current window
  584.     }
  585.     
  586.     tempWindow = GetNewCWindow( kBaseResID, nil, kMoveToFront );
  587.     
  588.     if ( tempWindow == nil )
  589.         DisplayFatalError( "\pERROR: could not open the window" );
  590.     
  591.     gWindow = tempWindow;
  592.     gWindowOpen = true;
  593.     
  594.     SetPort( gWindow );                    //    Draw IN the window!
  595.     SetWTitle( gWindow, windowTitle );    //    Set the window's name
  596.     
  597.     ShowWindow( gWindow ); 
  598.     
  599.     SetFileMenuStuff();
  600. }
  601.  
  602.  
  603. //
  604. //    CloseMyWindow
  605. //
  606. void CloseMyWindow( void )
  607. {
  608.     if ( gWindowOpen )    //    Just to be sure...
  609.     {
  610.         DisposeWindow( gWindow );
  611.         gWindowOpen = false;
  612.     }
  613.     
  614.     SetFileMenuStuff();
  615. }
  616.  
  617.  
  618. //
  619. //    CreateViewerInWindow
  620. //
  621. void CreateViewerInWindow( void )
  622. {
  623.     TQ3ViewerObject    myViewer;
  624.     
  625.     if ( gWindowOpen )
  626.     {
  627.         myViewer = MyCreateViewer( gWindow );
  628.         
  629.         if ( myViewer == nil )
  630.             DisplayAlert( "\pERROR: could not create viewer" );
  631.         else
  632.         {
  633.             gViewer = myViewer;
  634.             gViewerActive = true;
  635.         }
  636.     }
  637. }
  638.  
  639.  
  640. //
  641. //    MyCreateViewer
  642. //
  643. TQ3ViewerObject MyCreateViewer( WindowPtr myWindow )
  644. {
  645.     TQ3ViewerObject    myViewer;
  646.     Rect            myRect;
  647.     Point            myTL, myBR;
  648.     
  649.     //    Get rectangle enclosing the window's content region
  650.     myRect = myWindow->portRect;
  651.     
  652.     if ( EmptyRect( &myRect ) )
  653.         return( nil );
  654.     
  655.     //    Create a new viewer object in entire content region
  656.     myViewer = Q3ViewerNew( (CGrafPtr)myWindow, &myRect, kQ3ViewerDefault );
  657.     if ( myViewer == nil )
  658.         return( nil );
  659.     
  660.     Q3ViewerSetBounds( myViewer, &myRect );
  661.     
  662.     Q3ViewerDraw( myViewer );
  663.     
  664.     return( myViewer );
  665. }
  666.  
  667.  
  668. //
  669. //    Main
  670. //
  671. void main( void )
  672. {
  673.     TQ3Status    myStatus;
  674.     
  675.     ToolBoxInit();    //    Initialize toolbox managers
  676.     MenuBarInit();    //    Set up our menubar
  677.     
  678.     //    Check Gestalt for QuickDraw 3D:
  679.     if ( CheckGestaltFor3D() == true )
  680.     {
  681.         if ( MyEnvironmentHas3DViewer() != true )
  682.             DisplayFatalError( "\pERROR: QuickDraw 3D Viewer not installed!" );
  683.     }
  684.     else
  685.         DisplayFatalError( "\pERROR: QuickDraw 3D not installed!" );
  686.     
  687.     myStatus = Q3Initialize();
  688.     if ( myStatus == kQ3Failure )
  689.         DisplayFatalError( "\pERROR: Could not initialize QuickDraw 3D" );
  690.     
  691.     if ( Q3IsInitialized() == kQ3False )
  692.         DisplayFatalError( "\pERROR: Could not initialize QuickDraw 3D" );
  693.     
  694.     gWindowOpen = false;
  695.     gFileOpen = false;
  696.     gViewerActive = false;
  697.     SetFileMenuStuff();
  698.     SetEditMenuStuff();
  699.     
  700.     ShowAboutBox();
  701.     
  702.     MainLoop();    //    Go do the main even loop
  703.     
  704.     myStatus = Q3Exit();
  705.     if ( myStatus == kQ3Failure )
  706.         DisplayAlert( "\pERROR: could not unload QuickDraw 3D" );
  707. }
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.